package
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.geom.Point;
	import flash.text.TextFormat;
	import flash.utils.Timer;
	import flash.utils.getTimer;
	
	[SWF(backgroundColor = "0x000000", width = "465", height = "465", frameRate = 30)]
	public class Prime extends Sprite 
	{
		private var _stageW:uint;
		private var _stageH:uint;
		
		private const UP:uint = 0
		private const RIGHT:uint = 1;
		private const DOWN:uint = 2;
		private const LEFT:uint = 3;
		private const REMAIN_BASE:uint = 2;
		
		private var _count:uint;
		private var _remain:uint;
		private var _distance:uint;
		private var _direction:uint;
		private var _canvasBmd:BitmapData;
		private var _canvas:Bitmap;
		private var _dx:Number;
		private var _dy:Number;
		private var _max:uint;
		private var _now:uint;
		private var _timer:Timer;
		private var _fieldContainer:Sprite;
		private var _format:TextFormat;
		private var _margin:uint;
		
		private var prime:Vector.<int> = new Vector.<int>();
		
		public function Prime() 
		{
			_stageW = stage.stageWidth;
			_stageH = stage.stageHeight;
//			Wonderfl.capture_delay(10);
			_count = 1;
			_remain = 2;
			_distance = 1;
			_direction = RIGHT;
			_dx = 0;
			_dy = 0;
			_now = 1;
			_max = _stageW * _stageH;
			_timer = new Timer(1);
			_canvasBmd = new BitmapData(_stageW, _stageH, false, 0x000000);
			_canvas = new Bitmap(_canvasBmd);
			_fieldContainer = new Sprite();
			_margin = 1;
			
			addChild(_canvas);
			
			this.addEventListener(Event.ENTER_FRAME, onEnter);
		}
		
		private function onEnter(event:Event):void
		{
			var tick:int = getTimer();
			
			_canvasBmd.lock();
			while(getTimer() - tick < 33)
			{
				if(loop()) break;
			}
			_canvasBmd.unlock();
		}
		
		private function loop():Boolean 
		{
			var p:Point = generate(_now);
			var color:uint = 0x111111;
			if (IsPrime(_now))
			{
				prime.push(_now);
				color = 0xFF0000;
			}
			_canvasBmd.setPixel(_stageW / 2 + p.x, _stageH / 2 + p.y, color);
			_now++;
			if (_now == _max)
			{
				this.removeEventListener(Event.ENTER_FRAME, onEnter);
				return true;
			}
			return false;
		}
		
		private function generate(number:uint):Point
		{
			var returnX:Number = 0;
			var returnY:Number = 0;
			var dx:Number = 0;
			var dy:Number = 0;
			for (;_count < number;_count++)
			{
				if (--_remain == 0) 
				{
					switch (_direction) 
					{
						case UP: _distance++;_direction = LEFT; break;
						case DOWN: _distance++;
						default: _direction--; break;
					}
					
					_remain = _distance;
				}
				switch (_direction) 
				{
					case LEFT: --dx; break;
					case RIGHT: ++dx; break;
					case UP: --dy; break;
					case DOWN: ++dy; break;
				}
			}
			returnX = _dx + dx;
			returnY = _dy + dy;
			_dx += dx;
			_dy += dy;
			return new Point(returnX * _margin, returnY * _margin);
		}
		
		private function IsPrime(number:uint):Boolean
		{
			var leng:int = prime.length;
			var i:int = 1;
			
			if (number < 2)
			{
				return false;
			}
			else if (number == 2)
			{
				return true;
			}
			if (number & 1 == 0)
			{
				return false;
			}
			for( ; i < leng && prime[i]*prime[i] <= number; i++)
			{
				if(number%prime[i] == 0)
				{
					return false;
				}
			}
			return true;
		}
	}
}